#include "realoperationstest.h"

bool RealOperationsTest::run() {
    short count=0;

    if (!RealOperationsTest::realDivideEvaluateMeTest())
        std::cout << "ERROR " << ++count << " RealOperationsTest::realDivideEvaluateMeTest() faild!" << std::endl;
    if (!RealOperationsTest::realPowEvaluateMeTest())
        std::cout << "ERROR " << ++count << " RealOperationsTest::realPowEvaluateMeTest() faild!" << std::endl;
    if (!RealOperationsTest::realMinusEvaluateMeTest())
        std::cout << "ERROR " << ++count << " RealOperationsTest::realMinusEvaluateMeTest() faild!" << std::endl;
    if (!RealOperationsTest::realMultiplicationEvaluateMeTest())
        std::cout << "ERROR " << ++count << " RealOperationsTest::realMultiplicationEvaluateMeTest() faild!" << std::endl;
    if (!RealOperationsTest::realPlusEvaluateMeTest())
        std::cout << "ERROR " << ++count << " RealOperationsTest::realPlusEvaluateMeTest() faild!" << std::endl;
    if (!RealOperationsTest::RealVariableEvaluateMeTest())
        std::cout << "ERROR " << ++count << " RealOperationsTest::RealVariableEvaluateMeTest() faild!" << std::endl;
    if (!RealOperationsTest::RealVariableCopyConstructorTest())
        std::cout << "ERROR " << ++count << " RealOperationsTest::RealVariableCopyConstructorTest() faild!" << std::endl;

    return count==0;
}

bool RealOperationsTest::realDivideEvaluateMeTest() {
    RealDivide* realDivide = new RealDivide();
    LinkedList<double> evaluationStack;
    evaluationStack.addAtEnd(*(new double(1)));
    evaluationStack.addAtEnd(*(new double(2)));
    realDivide->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==0.5);
    assert(evaluationStack.getElementAtEnd()==0.5);
    evaluationStack.addAtEnd(*(new double(1)));
    realDivide->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==0.5);
    assert(evaluationStack.getElementAtEnd()==0.5);
    evaluationStack.addAtEnd(*(new double(0)));
    realDivide->evaluateMe(evaluationStack, 0);
    assert(RealValueCheck::isInf(evaluationStack.getElementAtStart()));
    delete realDivide;
    return true;
}

bool RealOperationsTest::realPowEvaluateMeTest() {
    RealPow* realPow = new RealPow();
    LinkedList<double> evaluationStack;

    evaluationStack.addAtEnd(*(new double(7)));
    evaluationStack.addAtEnd(*(new double(3)));
    realPow->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==343);
    assert(evaluationStack.getElementAtEnd()==343);
    delete &evaluationStack.pop();

    evaluationStack.addAtEnd(*(new double(32.01)));
    evaluationStack.addAtEnd(*(new double(1.54)));
    realPow->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()<208.0366914059 && evaluationStack.getElementAtStart()>208.0366914050);
    assert(evaluationStack.getElementAtEnd()<208.0366914059 && evaluationStack.getElementAtEnd()>208.0366914050);
    delete &evaluationStack.pop();

    evaluationStack.addAtEnd(*(new double(10)));
    evaluationStack.addAtEnd(*(new double(-2)));
    realPow->evaluateMe(evaluationStack, 0);

    assert(evaluationStack.getElementAtStart()>0.0099 && evaluationStack.getElementAtStart()<0.0101);
    assert(evaluationStack.getElementAtEnd()>0.0099 && evaluationStack.getElementAtEnd()<0.0101);
    delete &evaluationStack.pop();

    evaluationStack.addAtEnd(*(new double(7.91406)));
    evaluationStack.addAtEnd(*(new double(-1.41869)));
    realPow->evaluateMe(evaluationStack, 0);

    assert(evaluationStack.getElementAtStart()>0.053142 && evaluationStack.getElementAtStart()<0.053144);
    assert(evaluationStack.getElementAtEnd()>0.053142 && evaluationStack.getElementAtEnd()<0.053144);
    delete &evaluationStack.pop();


    evaluationStack.addAtEnd(*(new double(144)));
    evaluationStack.addAtEnd(*(new double(0.5)));
    realPow->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==12);
    assert(evaluationStack.getElementAtEnd()==12);
    delete &evaluationStack.pop();

    delete realPow;
    return true;
}

bool RealOperationsTest::realMinusEvaluateMeTest() {
    RealMinus* realMinus = new RealMinus();
    LinkedList<double> evaluationStack;

    evaluationStack.addAtEnd(*(new double(7)));
    evaluationStack.addAtEnd(*(new double(3)));
    realMinus->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==4);
    assert(evaluationStack.getElementAtEnd()==4);
    delete &evaluationStack.pop();

    evaluationStack.addAtEnd(*(new double(32.01)));
    evaluationStack.addAtEnd(*(new double(1.54)));
    realMinus->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==30.47);
    assert(evaluationStack.getElementAtEnd()==30.47);
    delete &evaluationStack.pop();

    evaluationStack.addAtEnd(*(new double(10)));
    evaluationStack.addAtEnd(*(new double(-2)));
    realMinus->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==12);
    assert(evaluationStack.getElementAtEnd()==12);
    delete &evaluationStack.pop();

    evaluationStack.addAtEnd(*(new double(144)));
    evaluationStack.addAtEnd(*(new double(0.5)));
    realMinus->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==143.5);
    assert(evaluationStack.getElementAtEnd()==143.5);
    delete &evaluationStack.pop();

    delete realMinus;
    return true;
}

bool RealOperationsTest::realMultiplicationEvaluateMeTest() {
    RealMultiplication* realMultiplication = new RealMultiplication();
    LinkedList<double> evaluationStack;

    evaluationStack.addAtEnd(*(new double(7)));
    evaluationStack.addAtEnd(*(new double(3)));
    realMultiplication->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==21);
    assert(evaluationStack.getElementAtEnd()==21);
    delete &evaluationStack.pop();

    evaluationStack.addAtEnd(*(new double(32.01)));
    evaluationStack.addAtEnd(*(new double(1.54)));
    realMultiplication->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()<49.2955 && evaluationStack.getElementAtStart()>49.2953);
    assert(evaluationStack.getElementAtStart()<49.2955 && evaluationStack.getElementAtStart()>49.2953);
    delete &evaluationStack.pop();

    evaluationStack.addAtEnd(*(new double(10)));
    evaluationStack.addAtEnd(*(new double(-2)));
    realMultiplication->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==-20);
    assert(evaluationStack.getElementAtEnd()==-20);
    delete &evaluationStack.pop();

    evaluationStack.addAtEnd(*(new double(144)));
    evaluationStack.addAtEnd(*(new double(0.5)));
    realMultiplication->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==72);
    assert(evaluationStack.getElementAtEnd()==72);
    delete &evaluationStack.pop();

    delete realMultiplication;
    return true;
}

bool RealOperationsTest::realPlusEvaluateMeTest() {
    RealPlus* realPlus = new RealPlus();
    LinkedList<double> evaluationStack;

    evaluationStack.addAtEnd(*(new double(7)));
    evaluationStack.addAtEnd(*(new double(3)));
    realPlus->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==10);
    assert(evaluationStack.getElementAtEnd()==10);
    delete &evaluationStack.pop();

    evaluationStack.addAtEnd(*(new double(32.01)));
    evaluationStack.addAtEnd(*(new double(1.54)));
    realPlus->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==33.55);
    assert(evaluationStack.getElementAtEnd()==33.55);
    delete &evaluationStack.pop();

    evaluationStack.addAtEnd(*(new double(10)));
    evaluationStack.addAtEnd(*(new double(-2)));
    realPlus->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==8);
    assert(evaluationStack.getElementAtEnd()==8);
    delete &evaluationStack.pop();

    evaluationStack.addAtEnd(*(new double(144)));
    evaluationStack.addAtEnd(*(new double(0.5)));
    realPlus->evaluateMe(evaluationStack, 0);
    assert(evaluationStack.getElementAtStart()==144.5);
    assert(evaluationStack.getElementAtEnd()==144.5);
    delete &evaluationStack.pop();

    delete realPlus;
    return true;
}

bool RealOperationsTest::RealVariableEvaluateMeTest() {
    RealVariable* realVariable1 = new RealVariable('x',8);
    LinkedList<double> evaluationStack;
    double* array = new double[10];
    for(int i=10; i--;)
        array[i]=i;

    evaluationStack.addAtEnd(*(new double(7)));
    evaluationStack.addAtEnd(*(new double(3)));
    realVariable1->evaluateMe(evaluationStack, array);
    assert(evaluationStack.getElementAtStart()==7);
    assert(evaluationStack.getElementAtEnd()==8);
    delete realVariable1;

    RealVariable* realVariable2 = new RealVariable('y',2);
    evaluationStack.addAtEnd(*(new double(32.01)));
    evaluationStack.addAtEnd(*(new double(1.54)));
    realVariable2->evaluateMe(evaluationStack, array);
    assert(evaluationStack.getElementAtStart()==7);
    assert(evaluationStack.getElementAtEnd()==2);

    evaluationStack.addAtEnd(*(new double(10)));
    evaluationStack.addAtEnd(*(new double(-2)));
    realVariable2->evaluateMe(evaluationStack, array);
    assert(evaluationStack.getElementAtStart()==7);
    assert(evaluationStack.getElementAtEnd()==2);
    delete realVariable2;

    RealVariable* realVariable3 = new RealVariable('z',0);
    evaluationStack.addAtEnd(*(new double(144)));
    evaluationStack.addAtEnd(*(new double(0.5)));
    realVariable3->evaluateMe(evaluationStack, array);
    assert(evaluationStack.getElementAtStart()==7);
    assert(evaluationStack.getElementAtEnd()==0);

    delete[] array;
    delete realVariable3;
    return true;
}

bool RealOperationsTest::RealVariableCopyConstructorTest() {
    unsigned int testNumber = 90;
    RealVariable* test = new RealVariable('c', testNumber);
    RealVariable* test2 = new RealVariable(*test);
    assert(test2->getSign()=='c');
    assert(*test2==*test);
    delete test;
    delete test2;
    return true;
}
